{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "In this notebook, you will implement the forward longitudinal vehicle model. The model accepts throttle inputs and steps through the longitudinal dynamic equations. Once implemented, you will be given a set of inputs that drives over a small road slope to test your model.\n",
    "\n",
    "The input to the model is a throttle percentage $x_\\theta \\in [0,1]$ which provides torque to the engine and subsequently accelerates the vehicle for forward motion. \n",
    "\n",
    "The dynamic equations consist of many stages to convert throttle inputs to wheel speed (engine -> torque converter -> transmission -> wheel). These stages are bundled together in a single inertia term $J_e$ which is used in the following combined engine dynamic equations.\n",
    "\n",
    "\\begin{align}\n",
    "    J_e \\dot{\\omega}_e &= T_e - (GR)(r_{eff} F_{load}) \\\\ m\\ddot{x} &= F_x - F_{load}\n",
    "\\end{align}\n",
    "\n",
    "Where $T_e$ is the engine torque, $GR$ is the gear ratio, $r_{eff}$ is the effective radius, $m$ is the vehicle mass, $x$ is the vehicle position, $F_x$ is the tire force, and $F_{load}$ is the total load force. \n",
    "\n",
    "The engine torque is computed from the throttle input and the engine angular velocity $\\omega_e$ using a simplified quadratic model. \n",
    "\n",
    "\\begin{align}\n",
    "    T_e = x_{\\theta}(a_0 + a_1 \\omega_e + a_2 \\omega_e^2)\n",
    "\\end{align}\n",
    "\n",
    "The load forces consist of aerodynamic drag $F_{aero}$, rolling friction $R_x$, and gravitational force $F_g$ from an incline at angle $\\alpha$. The aerodynamic drag is a quadratic model and the friction is a linear model.\n",
    "\n",
    "\\begin{align}\n",
    "    F_{load} &= F_{aero} + R_x + F_g \\\\\n",
    "    F_{aero} &= \\frac{1}{2} C_a \\rho A \\dot{x}^2 = c_a \\dot{x}^2\\\\\n",
    "    R_x &= N(\\hat{c}_{r,0} + \\hat{c}_{r,1}|\\dot{x}| + \\hat{c}_{r,2}\\dot{x}^2) \\approx c_{r,1} \\dot{x}\\\\\n",
    "    F_g &= mg\\sin{\\alpha}\n",
    "\\end{align}\n",
    "\n",
    "Note that the absolute value is ignored for friction since the model is used for only forward motion ($\\dot{x} \\ge 0$). \n",
    " \n",
    "The tire force is computed using the engine speed and wheel slip equations.\n",
    "\n",
    "\\begin{align}\n",
    "    \\omega_w &= (GR)\\omega_e \\\\\n",
    "    s &= \\frac{\\omega_w r_e - \\dot{x}}{\\dot{x}}\\\\\n",
    "    F_x &= \\left\\{\\begin{array}{lr}\n",
    "        cs, &  |s| < 1\\\\\n",
    "        F_{max}, & \\text{otherwise}\n",
    "        \\end{array}\\right\\} \n",
    "\\end{align}\n",
    "\n",
    "Where $\\omega_w$ is the wheel angular velocity and $s$ is the slip ratio. \n",
    "\n",
    "We setup the longitudinal model inside a Python class below. The vehicle begins with an initial velocity of 5 m/s and engine speed of 100 rad/s. All the relevant parameters are defined and like the bicycle model, a sampling time of 10ms is used for numerical integration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.image as mpimg\n",
    "\n",
    "class Vehicle():\n",
    "    def __init__(self):\n",
    " \n",
    "        # ==================================\n",
    "        #  Parameters\n",
    "        # ==================================\n",
    "    \n",
    "        #Throttle to engine torque\n",
    "        self.a_0 = 400\n",
    "        self.a_1 = 0.1\n",
    "        self.a_2 = -0.0002\n",
    "        \n",
    "        # Gear ratio, effective radius, mass + inertia\n",
    "        self.GR = 0.35\n",
    "        self.r_e = 0.3\n",
    "        self.J_e = 10\n",
    "        self.m = 2000\n",
    "        self.g = 9.81\n",
    "        \n",
    "        # Aerodynamic and friction coefficients\n",
    "        self.c_a = 1.36\n",
    "        self.c_r1 = 0.01\n",
    "        \n",
    "        # Tire force \n",
    "        self.c = 10000\n",
    "        self.F_max = 10000\n",
    "        \n",
    "        # State variables\n",
    "        self.x = 0\n",
    "        self.v = 5\n",
    "        self.a = 0\n",
    "        self.w_e = 100\n",
    "        self.w_e_dot = 0\n",
    "        \n",
    "        self.sample_time = 0.01\n",
    "        \n",
    "    def reset(self):\n",
    "        # reset state variables\n",
    "        self.x = 0\n",
    "        self.v = 5\n",
    "        self.a = 0\n",
    "        self.w_e = 100\n",
    "        self.w_e_dot = 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implement the combined engine dynamic equations along with the force equations in the cell below. The function $\\textit{step}$ takes the throttle $x_\\theta$ and incline angle $\\alpha$ as inputs and performs numerical integration over one timestep to update the state variables. Hint: Integrate to find the current position, velocity, and engine speed first, then propagate those values into the set of equations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Vehicle(Vehicle):\n",
    "    def step(self, throttle, alpha):\n",
    "        w_w = self.GR * self.w_e\n",
    "        s = (w_w * self.r_e - self.v) / self.v\n",
    "        if abs(s) < 1:\n",
    "            F_x = self.c * s\n",
    "        else:\n",
    "            F_x = self.F_max\n",
    "        F_aero = self.c_a * (self.v ** 2)\n",
    "        R_x = self.c_r1 * self.v\n",
    "        F_g = self.m * self.g * np.sin(alpha)\n",
    "        F_load = R_x + F_aero + F_g\n",
    "        self.a = (F_x - F_load) / self.m\n",
    "        self.v += self.a * self.sample_time\n",
    "        self.x += self.v * self.sample_time\n",
    "        T_e = throttle * (self.a_0 + self.a_1 * self.w_e + self.a_2 * self.w_e ** 2)\n",
    "        self.w_e_dot = (T_e - self.GR * self.r_e * F_load) / self.J_e\n",
    "        self.w_e += self.w_e_dot * self.sample_time\n",
    "        pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using the model, you can send constant throttle inputs to the vehicle in the cell below. You will observe that the velocity converges to a fixed value based on the throttle input due to the aerodynamic drag and tire force limit. A similar velocity profile can be seen by setting a negative incline angle $\\alpha$. In this case, gravity accelerates the vehicle to a terminal velocity where it is balanced by the drag force."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sample_time = 0.01\n",
    "time_end = 100\n",
    "model = Vehicle()\n",
    "\n",
    "t_data = np.arange(0,time_end,sample_time)\n",
    "v_data = np.zeros_like(t_data)\n",
    "\n",
    "# throttle percentage between 0 and 1\n",
    "throttle = 0.2\n",
    "\n",
    "# incline angle (in radians)\n",
    "alpha = 0\n",
    "\n",
    "for i in range(t_data.shape[0]):\n",
    "    v_data[i] = model.v\n",
    "    model.step(throttle, alpha)\n",
    "    \n",
    "plt.plot(t_data, v_data)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now drive the vehicle over a slope as shown in the diagram below.\n",
    "\n",
    "![ramp](ramp.png)\n",
    "\n",
    "To climb the slope, a trapezoidal throttle input is provided for the next 20 seconds as shown in the figure below. \n",
    "\n",
    "![throttle](throttle.png)\n",
    "\n",
    "The vehicle begins at 20% throttle and gradually increases to 50% throttle. This is maintained for 10 seconds as the vehicle climbs the steeper slope. Afterwards, the vehicle reduces the throttle to 0.\n",
    "\n",
    "In the cell below, implement the ramp angle profile $\\alpha (x)$ and throttle profile $x_\\theta (t)$ and step them through the vehicle dynamics. The vehicle position $x(t)$ is saved in the array $\\textit{x_data}$. This will be used to grade your solution.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "time_end = 20\n",
    "t_data = np.arange(0,time_end,sample_time)\n",
    "x_data = np.zeros_like(t_data)\n",
    "s_data = np.zeros_like(t_data)\n",
    "\n",
    "# reset the states\n",
    "model.reset()\n",
    "\n",
    "# ==================================\n",
    "#  Learner solution begins here\n",
    "# ==================================\n",
    "throttle_data = np.zeros_like(t_data)\n",
    "alpha_data = np.ones_like(t_data) * np.arctan(3 / 60)\n",
    "\n",
    "for i, t in enumerate(t_data):\n",
    "    \n",
    "    # throttle percentage between 0 and 1\n",
    "    # incline angle (in radians)\n",
    "    if t < 5:\n",
    "        throttle_data[i] = 0.2 + (0.5 - 0.2) / 5 * t\n",
    "    elif t < 15:\n",
    "        throttle_data[i] = 0.5\n",
    "    else:\n",
    "        throttle_data[i] = 0.5 - 0.5 / 5 * (t - 15)\n",
    "\n",
    "for i in range(t_data.shape[0]):\n",
    "    v_data[i] = model.v\n",
    "    \n",
    "    if model.x < 60:\n",
    "        alpha_data[i] = np.arctan(3 / 60)\n",
    "    elif model.x < 150:\n",
    "        alpha_data[i] = np.arctan((12-3) / 90)\n",
    "    else:\n",
    "        alpha_data[i] = 0\n",
    "        \n",
    "    model.step(throttle_data[i], alpha_data[i])\n",
    "    \n",
    "    x_data[i] = model.x\n",
    "    v_data[i] = model.v\n",
    "    w_w = model.GR * model.w_e\n",
    "    s_data[i] = (w_w * model.r_e - model.v) / model.v\n",
    "    \n",
    "\n",
    "# ==================================\n",
    "#  Learner solution ends here\n",
    "# ==================================\n",
    "\n",
    "# Plot x vs t for visualization\n",
    "plt.plot(t_data, x_data)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you have implemented the vehicle model and inputs correctly, you should see that the vehicle crosses the ramp at ~15s where the throttle input begins to decrease.\n",
    "\n",
    "The cell below will save the time and vehicle inputs as text file named $\\textit{xdata.txt}$. To locate the file, change the end of your web directory to $\\textit{/notebooks/Course_1_Module_4/xdata.txt}$\n",
    "\n",
    "Once you are there, you can download the file and submit to the Coursera grader to complete this assessment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = np.vstack([t_data, x_data]).T\n",
    "np.savetxt('xdata.txt', data, delimiter=', ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Congratulations! You have now completed the assessment! Feel free to test the vehicle model with different inputs in the cell below, and see what trajectories they form. In the next module, you will see the longitudinal model being used for speed control. See you there!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'y_data' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-17-82755b6cbdbb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     15\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maxis\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'equal'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 16\u001b[0;31m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx_data\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     17\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'y_data' is not defined"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYYAAAD8CAYAAABzTgP2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAEHJJREFUeJzt3X+o3fddx/Hna8nC1E3S2tsuzQ8bNQzjmFs5xIr+MV03kjiaKg5a0IZtEIIGNlQ0WlBEhG0FHcXQEmcxxWopbGOhy8jaMtk/tuvNbLPFNOtdcOaa2GaK3aRgiHv7x/1m3M/dubk/vif3R/t8wJdzvt/P+3O+7w8H8sr3fM9JUlVIknTFG5a7AUnSymIwSJIaBoMkqWEwSJIaBoMkqWEwSJIaBoMkqWEwSJIaBoMkqbF2uRtYjBtuuKFuueWW5W5DklaVEydOfLuqxuaqW5XBcMsttzA+Pr7cbUjSqpLkW/Op86MkSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNUYSDEl2JjmTZCLJwSHjSXJ/N34yya3d8Tcl+UqS55OcSvKno+hHkrR4vYMhyRrgELAL2A7cnWT7jLJdwLZu2wc80B3/X+CXq+pngXcCO5Pc1rcnSdLijeKKYQcwUVVnq+oS8CiwZ0bNHuDhmvI0sD7Jhm7/f7qaN3ZbjaAnSdIijSIYNgLnpu1PdsfmVZNkTZLngJeBJ6rqmRH0JElapFEEQ4Ycm/m3/llrqur/quqdwCZgR5K3Dz1Jsi/JeJLxixcv9mpYkjS7UQTDJLB52v4m4PxCa6rqv4F/BHYOO0lVHa6qQVUNxsbm/J/pJEmLNIpgeBbYlmRrknXAXcDRGTVHgXu6byfdBrxSVReSjCVZD5Dkh4DbgRdG0JMkaZF6/5/PVXU5yQHgOLAGeKiqTiXZ340/CBwDdgMTwKvAB7vpG4Aj3Teb3gA8VlWP9+1JkrR4qVp9XwIaDAY1Pj6+3G1I0qqS5ERVDeaq85fPkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJaowkGJLsTHImyUSSg0PGk+T+bvxkklu745uTfCnJ6SSnknxkFP1IkhavdzAkWQMcAnYB24G7k2yfUbYL2NZt+4AHuuOXgd+tqp8GbgN+e8hcSdISGsUVww5goqrOVtUl4FFgz4yaPcDDNeVpYH2SDVV1oaq+ClBV3wVOAxtH0JMkaZFGEQwbgXPT9if5wT/c56xJcgvwLuCZYSdJsi/JeJLxixcv9mxZkjSbUQRDhhyrhdQkeTPwaeCjVfWdYSepqsNVNaiqwdjY2KKblSRd3SiCYRLYPG1/E3B+vjVJ3shUKDxSVZ8ZQT+SpB5GEQzPAtuSbE2yDrgLODqj5ihwT/ftpNuAV6rqQpIAfwOcrqq/GEEvkqSe1vZ9gaq6nOQAcBxYAzxUVaeS7O/GHwSOAbuBCeBV4IPd9F8AfhP4WpLnumN/VFXH+vYlSVqcVM28HbDyDQaDGh8fX+42JGlVSXKiqgZz1fnLZ0lSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSw2CQJDUMBklSYyTBkGRnkjNJJpIcHDKeJPd34yeT3Dpt7KEkLyf5+ih6kST10zsYkqwBDgG7gO3A3Um2zyjbBWzrtn3AA9PG/hbY2bcPSdJojOKKYQcwUVVnq+oS8CiwZ0bNHuDhmvI0sD7JBoCq+jLwXyPoQ5I0AqMIho3AuWn7k92xhdZIklaAUQRDhhyrRdRc/STJviTjScYvXry4kKmSpAUYRTBMApun7W8Czi+i5qqq6nBVDapqMDY2tqhGJUlzG0UwPAtsS7I1yTrgLuDojJqjwD3dt5NuA16pqgsjOLckacR6B0NVXQYOAMeB08BjVXUqyf4k+7uyY8BZYAL4a+C3rsxP8g/APwFvSzKZ5MN9e5IkLV6qFvRR/4owGAxqfHx8uduQpFUlyYmqGsxV5y+fJUkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEkNg0GS1DAYJEmNkQRDkp1JziSZSHJwyHiS3N+Nn0xy63znSpKWVu9gSLIGOATsArYDdyfZPqNsF7Ct2/YBDyxgriRpCY3iimEHMFFVZ6vqEvAosGdGzR7g4ZryNLA+yYZ5zpUkLaFRBMNG4Ny0/cnu2Hxq5jNXkrSERhEMGXKs5lkzn7lTL5DsSzKeZPzixYsLbFGSNF+jCIZJYPO0/U3A+XnWzGcuAFV1uKoGVTUYGxvr3bQkabhRBMOzwLYkW5OsA+4Cjs6oOQrc03076Tbglaq6MM+5kqQltLbvC1TV5SQHgOPAGuChqjqVZH83/iBwDNgNTACvAh+82ty+PUmSFi9VQz/SX9EGg0GNj48vdxuStKokOVFVg7nq/OWzJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGgaDJKlhMEiSGr2CIcn1SZ5I8mL3eN0sdTuTnEkykeTgtOMfSHIqyfeSDPr0Ikkajb5XDAeBp6pqG/BUt99IsgY4BOwCtgN3J9neDX8d+DXgyz37kCSNSN9g2AMc6Z4fAe4cUrMDmKiqs1V1CXi0m0dVna6qMz17kCSNUN9guKmqLgB0jzcOqdkInJu2P9kdkyStQGvnKkjyJPDWIUP3zvMcGXKs5jl3eh/7gH0AW7ZsWeh0SdI8zRkMVXX7bGNJXkqyoaouJNkAvDykbBLYPG1/E3B+oY1W1WHgMMBgMFhwsEiS5qfvR0lHgb3d873A54bUPAtsS7I1yTrgrm6eJGkF6hsMHwPem+RF4L3dPkluTnIMoKouAweA48Bp4LGqOtXV/WqSSeDngc8nOd6zH0lST6lafZ/KDAaDGh8fX+42JGlVSXKiqub8zZi/fJYkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNXoFQ5LrkzyR5MXu8bpZ6nYmOZNkIsnBacfvS/JCkpNJPptkfZ9+JEn99b1iOAg8VVXbgKe6/UaSNcAhYBewHbg7yfZu+Ang7VX1DuAbwB/27EeS1FPfYNgDHOmeHwHuHFKzA5ioqrNVdQl4tJtHVX2xqi53dU8Dm3r2I0nqqW8w3FRVFwC6xxuH1GwEzk3bn+yOzfQh4As9+5Ek9bR2roIkTwJvHTJ07zzPkSHHasY57gUuA49cpY99wD6ALVu2zPPUkqSFmjMYqur22caSvJRkQ1VdSLIBeHlI2SSwedr+JuD8tNfYC7wfeE9VFbOoqsPAYYDBYDBrnSSpn74fJR0F9nbP9wKfG1LzLLAtydYk64C7unkk2Qn8AXBHVb3asxdJ0gj0DYaPAe9N8iLw3m6fJDcnOQbQ3Vw+ABwHTgOPVdWpbv5fAW8BnkjyXJIHe/YjSeppzo+Srqaq/hN4z5Dj54Hd0/aPAceG1P1Un/NLkkbPXz5LkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySpYTBIkhoGgySp0SsYklyf5IkkL3aP181StzPJmSQTSQ5OO/5nSU4meS7JF5Pc3KcfSVJ/fa8YDgJPVdU24Kluv5FkDXAI2AVsB+5Osr0bvq+q3lFV7wQeB/64Zz+SpJ76BsMe4Ej3/Ahw55CaHcBEVZ2tqkvAo908quo70+p+BKie/UiSelrbc/5NVXUBoKouJLlxSM1G4Ny0/Ung567sJPlz4B7gFeCXZjtRkn3APoAtW7b0bFuSNJs5rxiSPJnk60O2PfM8R4Yc+/6VQVXdW1WbgUeAA7O9SFUdrqpBVQ3GxsbmeWpJ0kLNecVQVbfPNpbkpSQbuquFDcDLQ8omgc3T9jcB54fU/T3weeBP5upJknTt9L3HcBTY2z3fC3xuSM2zwLYkW5OsA+7q5pFk27S6O4AXevYjSeqp7z2GjwGPJfkw8G/ABwC6r51+qqp2V9XlJAeA48Aa4KGqOnVlfpK3Ad8DvgXs79mPJKmnVK2+LwINBoMaHx9f7jYkaVVJcqKqBnPV+ctnSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNQwGSVLDYJAkNVblP6KX5CJT/xrranMD8O3lbmIJvd7WC6759WK1rvnHq2rO/+lsVQbDapVkfD7/suFrxettveCaXy9e62v2oyRJUsNgkCQ1DIaldXi5G1hir7f1gmt+vXhNr9l7DJKkhlcMkqSGwTBCSa5P8kSSF7vH62ap25nkTJKJJAeHjP9ekkpyw7Xvup++a05yX5IXkpxM8tkk65eu+4WZx/uWJPd34yeT3DrfuSvVYtecZHOSLyU5neRUko8sffeL0+d97sbXJPnnJI8vXdcjVlVuI9qATwAHu+cHgY8PqVkDfBP4CWAd8Dywfdr4ZuA4U7/TuGG513St1wy8D1jbPf/4sPkrYZvrfetqdgNfAALcBjwz37krceu55g3Ard3ztwDfeK2vedr47wB/Dzy+3OtZ7OYVw2jtAY50z48Adw6p2QFMVNXZqroEPNrNu+Ivgd8HVsvNn15rrqovVtXlru5pYNM17nex5nrf6PYfrilPA+uTbJjn3JVo0WuuqgtV9VWAqvoucBrYuJTNL1Kf95kkm4BfAT61lE2PmsEwWjdV1QWA7vHGITUbgXPT9ie7YyS5A/j3qnr+Wjc6Qr3WPMOHmPqb2Eo0nzXMVjPf9a80fdb8fUluAd4FPDPyDkev75o/ydRf7L53rRpcCmuXu4HVJsmTwFuHDN0735cYcqyS/HD3Gu9bbG/XyrVa84xz3AtcBh5ZWHdLZs41XKVmPnNXoj5rnhpM3gx8GvhoVX1nhL1dK4tec5L3Ay9X1Ykk7x55Z0vIYFigqrp9trEkL125jO4uLV8eUjbJ1H2EKzYB54GfBLYCzye5cvyrSXZU1X+MbAGLcA3XfOU19gLvB95T3Ye0K9BV1zBHzbp5zF2J+qyZJG9kKhQeqarPXMM+R6nPmn8duCPJbuBNwI8m+buq+o1r2O+1sdw3OV5LG3Af7Y3YTwypWQucZSoErtzc+pkhdf/K6rj53GvNwE7gX4Cx5V7LHOuc831j6rPl6Tclv7KQ93ylbT3XHOBh4JPLvY6lWvOMmnezim8+L3sDr6UN+DHgKeDF7vH67vjNwLFpdbuZ+pbGN4F7Z3mt1RIMvdYMTDD1ee1z3fbgcq/pKmv9gTUA+4H93fMAh7rxrwGDhbznK3Fb7JqBX2TqI5iT097b3cu9nmv9Pk97jVUdDP7yWZLU8FtJkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJahgMkqSGwSBJavw/VoAFuUYfv7IAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sample_time = 0.01\n",
    "time_end = 30\n",
    "model.reset()\n",
    "\n",
    "t_data = np.arange(0,time_end,sample_time)\n",
    "x_data = np.zeros_like(t_data)\n",
    "\n",
    "# ==================================\n",
    "#  Test various inputs here\n",
    "# ==================================\n",
    "for i in range(t_data.shape[0]):\n",
    "\n",
    "    model.step(0,0)\n",
    "    \n",
    "plt.axis('equal')\n",
    "plt.plot(x_data, y_data)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
